﻿// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information
// 
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to you under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
// 
// http://www.apache.org/licenses/LICENSE-2.0
// 
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// 

using System;
using System.Collections;
using log4net;
using log4net.ObjectRenderer;
using log4net.Core;
using log4net.Plugin;
using log4net.Repository.Hierarchy;
using log4net.Util;

namespace log4net.Repository
{
    /// <summary>Delegate used to handle logger repository shutdown event notifications</summary>
    /// <param name="sender">The <see cref="ILoggerRepository"/> that is shutting down.</param>
    /// <param name="e">Empty event args</param>
    /// <remarks>
    /// <para>
    /// Delegate used to handle logger repository shutdown event notifications.
    /// </para>
    /// </remarks>
    public delegate void LoggerRepositoryShutdownEventHandler(object sender, EventArgs e);

    /// <summary>Delegate used to handle logger repository configuration reset event notifications</summary>
    /// <param name="sender">The <see cref="ILoggerRepository"/> that has had its configuration reset.</param>
    /// <param name="e">Empty event args</param>
    /// <remarks>
    /// <para>
    /// Delegate used to handle logger repository configuration reset event notifications.
    /// </para>
    /// </remarks>
    public delegate void LoggerRepositoryConfigurationResetEventHandler(object sender, EventArgs e);

    /// <summary>Delegate used to handle event notifications for logger repository configuration changes.</summary>
    /// <param name="sender">The <see cref="ILoggerRepository"/> that has had its configuration changed.</param>
    /// <param name="e">Empty event arguments.</param>
    /// <remarks>
    /// <para>
    /// Delegate used to handle event notifications for logger repository configuration changes.
    /// </para>
    /// </remarks>
    public delegate void LoggerRepositoryConfigurationChangedEventHandler(object sender, EventArgs e);

    /// <summary>Interface implemented by logger repositories.</summary>
    /// <remarks>
    /// <para>
    /// This interface is implemented by logger repositories. e.g. 
    /// <see cref="Hierarchy"/>.
    /// </para>
    /// <para>
    /// This interface is used by the <see cref="LogManager"/>
    /// to obtain <see cref="ILog"/> interfaces.
    /// </para>
    /// </remarks>
    /// <author>Nicko Cadell</author>
    /// <author>Gert Driesen</author>
    public interface ILoggerRepository
    {
        /// <summary>The name of the repository</summary>
        /// <value>
        /// The name of the repository
        /// </value>
        /// <remarks>
        /// <para>
        /// The name of the repository.
        /// </para>
        /// </remarks>
        string Name { get; set; }

        /// <summary>RendererMap accesses the object renderer map for this repository.</summary>
        /// <value>
        /// RendererMap accesses the object renderer map for this repository.
        /// </value>
        /// <remarks>
        /// <para>
        /// RendererMap accesses the object renderer map for this repository.
        /// </para>
        /// <para>
        /// The RendererMap holds a mapping between types and
        /// <see cref="IObjectRenderer"/> objects.
        /// </para>
        /// </remarks>
        RendererMap RendererMap { get; }

        /// <summary>The plugin map for this repository.</summary>
        /// <value>
        /// The plugin map for this repository.
        /// </value>
        /// <remarks>
        /// <para>
        /// The plugin map holds the <see cref="IPlugin"/> instances
        /// that have been attached to this repository.
        /// </para>
        /// </remarks>
        PluginMap PluginMap { get; }

        /// <summary>Get the level map for the Repository.</summary>
        /// <remarks>
        /// <para>
        /// Get the level map for the Repository.
        /// </para>
        /// <para>
        /// The level map defines the mappings between
        /// level names and <see cref="Level"/> objects in
        /// this repository.
        /// </para>
        /// </remarks>
        LevelMap LevelMap { get; }

        /// <summary>The threshold for all events in this repository</summary>
        /// <value>
        /// The threshold for all events in this repository
        /// </value>
        /// <remarks>
        /// <para>
        /// The threshold for all events in this repository.
        /// </para>
        /// </remarks>
        Level Threshold { get; set; }

        /// <summary>
        /// Check if the named logger exists in the repository. If so return
        /// its reference, otherwise returns <c>null</c>.
        /// </summary>
        /// <param name="name">The name of the logger to lookup</param>
        /// <returns>The Logger object with the name specified</returns>
        /// <remarks>
        /// <para>
        /// If the names logger exists it is returned, otherwise
        /// <c>null</c> is returned.
        /// </para>
        /// </remarks>
        ILogger Exists(string name);

        /// <summary>Returns all the currently defined loggers as an Array.</summary>
        /// <returns>All the defined loggers</returns>
        /// <remarks>
        /// <para>
        /// Returns all the currently defined loggers as an Array.
        /// </para>
        /// </remarks>
        ILogger[] GetCurrentLoggers();

        /// <summary>Returns a named logger instance</summary>
        /// <param name="name">The name of the logger to retrieve</param>
        /// <returns>The logger object with the name specified</returns>
        /// <remarks>
        /// <para>
        /// Returns a named logger instance.
        /// </para>
        /// <para>
        /// If a logger of that name already exists, then it will be
        /// returned.  Otherwise, a new logger will be instantiated and
        /// then linked with its existing ancestors as well as children.
        /// </para>
        /// </remarks>
        ILogger GetLogger(string name);

        /// <summary>Shutdown the repository</summary>
        /// <remarks>
        /// <para>
        /// Shutting down a repository will <i>safely</i> close and remove
        /// all appenders in all loggers including the root logger.
        /// </para>
        /// <para>
        /// Some appenders need to be closed before the
        /// application exists. Otherwise, pending logging events might be
        /// lost.
        /// </para>
        /// <para>
        /// The <see cref="M:Shutdown()"/> method is careful to close nested
        /// appenders before closing regular appenders. This is allows
        /// configurations where a regular appender is attached to a logger
        /// and again to a nested appender.
        /// </para>
        /// </remarks>
        void Shutdown();

        /// <summary>Reset the repositories configuration to a default state</summary>
        /// <remarks>
        /// <para>
        /// Reset all values contained in this instance to their
        /// default state.
        /// </para>
        /// <para>
        /// Existing loggers are not removed. They are just reset.
        /// </para>
        /// <para>
        /// This method should be used sparingly and with care as it will
        /// block all logging until it is completed.
        /// </para>
        /// </remarks>
        void ResetConfiguration();

        /// <summary>Log the <see cref="LoggingEvent"/> through this repository.</summary>
        /// <param name="logEvent">the event to log</param>
        /// <remarks>
        /// <para>
        /// This method should not normally be used to log.
        /// The <see cref="ILog"/> interface should be used 
        /// for routine logging. This interface can be obtained
        /// using the <see cref="M:log4net.LogManager.GetLogger(string)"/> method.
        /// </para>
        /// <para>
        /// The <c>logEvent</c> is delivered to the appropriate logger and
        /// that logger is then responsible for logging the event.
        /// </para>
        /// </remarks>
        void Log(LoggingEvent logEvent);

        /// <summary>Flag indicates if this repository has been configured.</summary>
        /// <value>
        /// Flag indicates if this repository has been configured.
        /// </value>
        /// <remarks>
        /// <para>
        /// Flag indicates if this repository has been configured.
        /// </para>
        /// </remarks>
        bool Configured { get; set; }

        /// <summary>
        /// Collection of internal messages captured during the most 
        /// recent configuration process.
        /// </summary>
        ICollection ConfigurationMessages { get; set; }

        /// <summary>Event to notify that the repository has been shutdown.</summary>
        /// <value>
        /// Event to notify that the repository has been shutdown.
        /// </value>
        /// <remarks>
        /// <para>
        /// Event raised when the repository has been shutdown.
        /// </para>
        /// </remarks>
        event LoggerRepositoryShutdownEventHandler ShutdownEvent;

        /// <summary>Event to notify that the repository has had its configuration reset.</summary>
        /// <value>
        /// Event to notify that the repository has had its configuration reset.
        /// </value>
        /// <remarks>
        /// <para>
        /// Event raised when the repository's configuration has been
        /// reset to default.
        /// </para>
        /// </remarks>
        event LoggerRepositoryConfigurationResetEventHandler ConfigurationReset;

        /// <summary>Event to notify that the repository has had its configuration changed.</summary>
        /// <value>
        /// Event to notify that the repository has had its configuration changed.
        /// </value>
        /// <remarks>
        /// <para>
        /// Event raised when the repository's configuration has been changed.
        /// </para>
        /// </remarks>
        event LoggerRepositoryConfigurationChangedEventHandler ConfigurationChanged;

        /// <summary>Repository specific properties</summary>
        /// <value>
        /// Repository specific properties
        /// </value>
        /// <remarks>
        /// <para>
        /// These properties can be specified on a repository specific basis.
        /// </para>
        /// </remarks>
        PropertiesDictionary Properties { get; }

        /// <summary>Returns all the Appenders that are configured as an Array.</summary>
        /// <returns>All the Appenders</returns>
        /// <remarks>
        /// <para>
        /// Returns all the Appenders that are configured as an Array.
        /// </para>
        /// </remarks>
        Appender.IAppender[] GetAppenders();
    }
}
